import mapboxgl from 'mapbox-gl'
import { QueryByDistanceParameters, BurstPipelineAnalystParameters, NetworkAnalystService } from '@supermapgis/iclient-mapboxgl'
import { SOURCENODE_IDS, URL_CONFIGS } from '@/constants'
import http from '@/utils/http'

let marker: any = null
let nameMarker: any = null
let edgeID: number
const facilityNameMarkers: any[] = []

async function queryPipeLine(e: any) {
  const { lng, lat } = e.lngLat
  const point = new mapboxgl.LngLat(lng, lat)
  const param = new QueryByDistanceParameters({
    queryParams: { name: 'pipe@pipe' },
    distance: 0.00001,
    geometry: point,
    isNearest: true,
    expectCount: 1
  })

  try {
    const res = await new mapboxgl.supermap.QueryService(URL_CONFIGS.PIPE_MAP_URL).queryByDistance(param)

    if (map.getLayer('pipe-line')) {
      map.removeLayer('pipe-line')
      map.removeSource('pipe-line')
    }

    if (marker) marker.remove()
    if (nameMarker) nameMarker.remove()

    if (res.result.recordsets.length > 0 && res.result.recordsets[0].features) {
      edgeID = res.result.recordsets[0].features.features[0].properties.SmID

      // 添加爆管点 Marker
      const svg = document.createElement('svg')
      svg.setAttribute('width', '24')
      svg.setAttribute('height', '24')
      svg.innerHTML = `
<?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M24 44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z" stroke="#d0021b" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path fill-rule="evenodd" clip-rule="evenodd" d="M24 34C29.5228 34 34 29.5228 34 24C34 18.4772 29.5228 14 24 14C18.4772 14 14 18.4772 14 24C14 29.5228 18.4772 34 24 34Z" stroke="#d0021b" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M24 4V44" stroke="#d0021b" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M4 24.0002L18 24.0086" stroke="#d0021b" stroke-width="4" stroke-linecap="round"/><path d="M4 24.0083L44 24.0083" stroke="#d0021b" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>
    `
      marker = new mapboxgl.Marker(svg).setLngLat([e.lngLat.lng, e.lngLat.lat]).addTo(map)

      // 添加爆管点名称 Marker
      const element = document.createElement('div')
      element.classList.add('pipe-point-name')
      element.innerText = '爆管点'
      nameMarker = new mapboxgl.Marker({
        element,
        anchor: 'left',
        offset: [10, 15]
      })
        .setLngLat([lng, lat])
        .addTo(map)

      map.addSource('pipe-line', {
        type: 'geojson',
        data: res.result.recordsets[0].features
      })
      map.addLayer({
        id: 'pipe-line',
        type: 'line',
        source: 'pipe-line',
        layout: { 'line-join': 'round', 'line-cap': 'round' },
        paint: { 'line-color': '#FFA500', 'line-width': 4 }
      })
    }
  } catch (error) {
    throw new Error(error instanceof Error ? error.message : '管网数据查询失败！')
  }
}

function selectPipePoint() {
  const hasPipe = hasPipeLayer()
  if (!hasPipe) return
  clearBurstAnalysis()
  map.on('click', queryPipeLine)
}

function clearBurstAnalysis() {
  const hasPipe = hasPipeLayer()
  if (!hasPipe) return
  map.off('click', queryPipeLine)
  // 移除爆管点跟管道
  if (map.getLayer('pipe-line')) {
    map.removeLayer('pipe-line')
    map.removeSource('pipe-line')
  }
  if (marker) marker.remove()
  if (nameMarker) nameMarker.remove()

  // 移除阀门点跟管道
  if (map.getLayer('valve-result-points')) {
    map.removeLayer('valve-result-points')
    map.removeSource('valve-result-points')
  }
  if (map.getLayer('pipe-result-line')) {
    map.removeLayer('pipe-result-line')
    map.removeSource('pipe-result-line')
  }
  facilityNameMarkers.forEach(function (marker) {
    marker.remove()
  })
}

async function burstAnalysis() {
  const hasPipe = hasPipeLayer()
  if (!hasPipe) return
  map.off('click', queryPipeLine)
  if (edgeID) {
    const parameter = new BurstPipelineAnalystParameters({
      sourceNodeIDs: SOURCENODE_IDS, //设施点ID数组
      edgeID: edgeID, //爆管弧段ID，既查询弧段内容
      nodeID: null, //爆管结点ID （注：edgeID 与 nodeID 不能同时使用）
      isUncertainDirectionValid: true //指定不确定流向是否有效
    })
    const BurstPipelineAnalystEventArgs = await new NetworkAnalystService(URL_CONFIGS.PIPE_ANALYSIS_URL).burstPipelineAnalyst(parameter)
    const result = BurstPipelineAnalystEventArgs.result
    //上下游中受爆管位置影响的弧段ID
    const edgeIDs = result.edges
    //爆管分析中受爆管位置影响的上下游的关键设施点ID
    const criticalNodes = result.criticalNodes
    queryFacilityAndPipePoint(criticalNodes, edgeIDs)
  }
}

async function queryFacilityAndPipePoint(facilityIDs: number[], edgeIDs: number[]) {
  try {
    const facilityIDsQueryParam = {
      getFeatureMode: 'SQL',
      datasetNames: ['pipe:pipe_Node'],
      maxFeatures: 1000,
      queryParameter: {
        attributeFilter: 'SmNodeID in ' + `(${facilityIDs.join(',')})`
      }
    }
    const edgeIDsQueryParam = {
      getFeatureMode: 'SQL',
      datasetNames: ['pipe:pipe'],
      maxFeatures: 1000,
      queryParameter: {
        attributeFilter: 'SMID in ' + `(${edgeIDs.join(',')})`
      }
    }

    const [facilityGeojson, pipeLineGeojson] = await Promise.all([
      http.post<GeoJSON.FeatureCollection<GeoJSON.Point>>(URL_CONFIGS.PIPE_DATA_URL, facilityIDsQueryParam),
      http.post<GeoJSON.FeatureCollection<GeoJSON.LineString>>(URL_CONFIGS.PIPE_DATA_URL, edgeIDsQueryParam)
    ])

    if (map.getLayer('valve-result-points')) {
      map.removeLayer('valve-result-points')
      map.removeSource('valve-result-points')
    }
    if (facilityNameMarkers.length) facilityNameMarkers.forEach((marker) => marker.remove())

    map.addSource('valve-result-points', {
      type: 'geojson',
      data: facilityGeojson
    })
    map.addLayer({
      id: 'valve-result-points',
      type: 'circle',
      source: 'valve-result-points',
      paint: { 'circle-radius': 6, 'circle-color': '#ff0000', 'circle-opacity': 1 }
    })

    facilityGeojson.features.forEach(function (feature) {
      const [lng, lat] = feature.geometry.coordinates
      const element = document.createElement('div')
      element.classList.add('valve-point-name')
      element.innerText = '需关闭阀门'
      const nameMarker = new mapboxgl.Marker({
        element,
        anchor: 'left',
        offset: [5, 15]
      })
        .setLngLat([lng, lat])
        .addTo(map)
      facilityNameMarkers.push(nameMarker)
    })

    if (map.getLayer('pipe-result-line')) {
      map.removeLayer('pipe-result-line')
      map.removeSource('pipe-result-line')
    }
    map.addSource('pipe-result-line', {
      type: 'geojson',
      data: pipeLineGeojson
    })
    map.addLayer({
      id: 'pipe-result-line',
      type: 'line',
      source: 'pipe-result-line',
      layout: { 'line-join': 'round', 'line-cap': 'round' },
      paint: { 'line-color': '#FF0000', 'line-width': 4 }
    })
  } catch (error) {
    throw new Error(error instanceof Error ? error.message : '管网数据查询失败！')
  }
}

function hasPipeLayer(): boolean {
  const layers = ['pipe-map', 'valve-points', 'valve-label']
  if (layers.every((layer) => map.getLayer(layer))) {
    return true
  } else {
    ElMessage.error('请先加载管网地图！')
    return false
  }
}

export { selectPipePoint, clearBurstAnalysis, burstAnalysis }
